package com.lanchetech.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.lanchetech.bean.vo.OrderSkuVO;
import com.lanchetech.common.enums.KdzsOrderStatusEnum;
import com.lanchetech.common.enums.KdzsRefundStatusEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.KuaidizsService;
import com.lanchetech.service.DaoService;
import com.raycloud.open.sdk.api.KdzsClient;
import com.raycloud.open.sdk.api.base.BaseKdzsOpenResponse;
import com.raycloud.open.sdk.api.base.exception.ApiRuleException;
import com.raycloud.open.sdk.api.base.print.MallOrder;
import com.raycloud.open.sdk.api.base.print.MallSkuProp;
import com.raycloud.open.sdk.api.base.print.PrintMallTrade;
import com.raycloud.open.sdk.api.request.KdzsPrintLoginUrlGetRequest;
import com.raycloud.open.sdk.api.request.KdzsPrintTradeCreateRequest;
import com.lanchetech.service.KdzsPrintTradeUpdateRequest;
import com.raycloud.open.sdk.api.request.KdzsPrintTradeRefundRequest;
import com.raycloud.open.sdk.api.response.KdzsPrintLoginUrlGetResponse;
import com.raycloud.open.sdk.api.response.KdzsPrintTradeCreateResponse;
import org.hashids.Hashids;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class KuaidizsServiceImpl implements KuaidizsService {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private String appkey = "93CAB43C30E34F53B98D18E83FBFBE49";

    private String appSecret = "1AA8203422C948EE9419133730E76BFB";


    @Autowired
    OrderSkuMapper orderSkuMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    OrderAddressMapper orderAddressMapper;

    @Autowired
    ShopMapper shopMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    AreaMapper areaMapper;

    @Autowired
    StreetMapper streetMapper;

    private KdzsClient getClient() {
        return new KdzsClient(appkey, appSecret);
    }

    /**
     * 获取免登陆链接
     *
     * @return
     */
    @Override
    public String getLoginUrl() {
        try {
            Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            Hashids hashids = new Hashids("kuaidizs", 16);
            String token = hashids.encode(merchant.getTenantId(), System.currentTimeMillis());
            Long tenantId = merchant.getTenantId();
            Shop shop = shopMapper.selectByPrimaryKey(tenantId);
            KdzsClient client = getClient();
            KdzsPrintLoginUrlGetRequest request = new KdzsPrintLoginUrlGetRequest();
            request.setUserName(appkey + "_" + shop.getShopName() + "_" + token);
            request.setSecret(appSecret);
            KdzsPrintLoginUrlGetResponse execute = client.execute(request);
            log.info("获取免登录链接返回结果{}", JSON.toJSONString(execute));
            if (execute != null) {
                return execute.getUrl();
            }
        } catch (ApiRuleException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param shop
     * @return
     */
    @Override
    public String getLoginUrl(Shop shop) {
        try {
            Hashids hashids = new Hashids("kuaidizs", 16);
            String token = hashids.encode(shop.getId(), System.currentTimeMillis());
            KdzsClient client = getClient();
            KdzsPrintLoginUrlGetRequest request = new KdzsPrintLoginUrlGetRequest();
            request.setUserName(appkey + "_" + shop.getShopName() + "_" + token);
            request.setSecret(appSecret);
            KdzsPrintLoginUrlGetResponse execute = client.execute(request);
            log.info("获取免登录链接返回结果{}", JSON.toJSONString(execute));
            if (execute != null) {
                return execute.getUrl();
            }
        } catch (ApiRuleException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建订单
     *
     * @return
     */
    @Override
    public KdzsPrintTradeCreateResponse createTrade(Orders orders) {
        try {
            Shop shop = shopMapper.selectByPrimaryKey(orders.getTenantId());
            if (shop.getMallUserId() > 0) {
                log.info("{}商户的mallUserId为空", shop.getShopName());
                //首次登陆快递助手获取mallUserId
                getLoginUrl(shop);
                log.info("{}店铺自动登陆快递助手，通过回调获取mallUserId", shop.getShopName());
                return null;
            }
            OrderAddress orderAddress = orderAddressMapper.findOneByOrderId(orders.getId());
            if (orderAddress != null) {
                List<OrderSkuVO> orderSkuVOS = orderSkuMapper.findAllByOrderId(orders.getId());
                Map<Long, Sku> skuMap = daoService.getSkuMap(orderSkuVOS.stream().map(OrderSkuVO::getSkuId).collect(Collectors.toList()));
                List<Long> areaIds = new ArrayList<>();
                areaIds.add(orderAddress.getArea());
                areaIds.add(orderAddress.getCity());
                areaIds.add(orderAddress.getProvince());
                List<Area> areaList = areaMapper.findAllbyIds(areaIds);
                Map<Long, String> areaMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(areaList)) {
                    areaList.stream().forEach(item -> {
                        areaMap.put(item.getId(), item.getName());
                    });
                }

                KdzsPrintTradeCreateRequest request = new KdzsPrintTradeCreateRequest();
                PrintMallTrade printMallTrade = new PrintMallTrade();
                printMallTrade.setStatus(KdzsOrderStatusEnum.ORDER_NO_PAY.getStatus());
                List<MallOrder> orderList = new ArrayList<>();
                orderSkuVOS.stream().forEach(item -> {
                    Sku sku = skuMap.get(item.getSkuId());
                    MallOrder mallOrder = new MallOrder();
                    mallOrder.setPayment(item.getPayAmount().toString());
                    mallOrder.setTotalFee(item.getDefaultPrice().toString());
                    mallOrder.setPrice(item.getPrice().toString());
                    mallOrder.setNumber(item.getCount());
                    //todo outerSkuId和skuId
                    mallOrder.setOuterSkuId(item.getSkuId().toString());
                    mallOrder.setSkuId(item.getSkuId().toString());
                    mallOrder.setItemId(item.getSpuId().toString());
                    mallOrder.setOuterId(orders.getTenantId().toString());
                    mallOrder.setTitle(item.getProductName());
                    mallOrder.setStatus(KdzsOrderStatusEnum.ORDER_NO_PAY.getStatus());
                    mallOrder.setPicPath(sku.getImage());
                    mallOrder.setOrderId(item.getId().toString());
                    mallOrder.setSaleProps(buildSkuProp(sku));
                    orderList.add(mallOrder);
                });
                printMallTrade.setOrders(orderList);
                List<Integer> countList = orderSkuVOS.stream().map(OrderSkuVO::getCount).collect(Collectors.toList());
                printMallTrade.setTotalNum(countList.stream().mapToInt(Integer::intValue).sum());
                printMallTrade.setModified(orders.getUpdatedAt());
                printMallTrade.setPayTime(orders.getPayTime());
                printMallTrade.setCreated(orders.getCreatedAt());
                printMallTrade.setPostFee(orders.getTotalFreight().toString());
                printMallTrade.setPayment(orders.getTotalPayAmount().toString());
                printMallTrade.setTotalFee(orders.getTotalProductAmount().toString());
                printMallTrade.setReceiverMobile(orderAddress.getPhone());
                printMallTrade.setReceiverAddress(orderAddress.getAddress());
                //街道
                if (orderAddress.getStreet() != null) {
                    Street street = streetMapper.findOneByStreet(orderAddress.getStreet());
                    if (street != null) {
                        printMallTrade.setReceiverTown(street.getName());
                    }
                }
                printMallTrade.setReceiverCounty(areaMap.get(orderAddress.getArea()));
                printMallTrade.setReceiverCity(areaMap.get(orderAddress.getCity()));
                printMallTrade.setReceiverProvince(areaMap.get(orderAddress.getProvince()));
                printMallTrade.setReceiverName(orderAddress.getName());
                printMallTrade.setTid(orders.getId().toString());
                request.setData(printMallTrade);
                request.setMallUserId(shop.getMallUserId());


                log.info("创建订单参数{}", JSON.toJSONString(request));
                KdzsClient client = getClient();
                KdzsPrintTradeCreateResponse execute = client.execute(request);
                log.info("创建订单返回{}", JSON.toJSONString(execute));
                return execute;
            }
        } catch (ApiRuleException e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 订单退款
     *
     * @param request
     * @return
     */
    @Override
    public BaseKdzsOpenResponse refundTrade(KdzsPrintTradeRefundRequest request) {
        try {
            KdzsClient client = getClient();
            BaseKdzsOpenResponse execute = client.execute(request);
            log.info("订单退款结果{}", JSON.toJSONString(execute));
            return execute;
        } catch (ApiRuleException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 修改快递状态
     */
    @Override
    public Boolean updateTrade(KdzsPrintTradeUpdateRequest req) {
        try {
            log.info("修改订单参数{}", JSON.toJSONString(req));
            KdzsClient client = getClient();
            BaseKdzsOpenResponse execute = client.execute(req);
            log.info("修改订单{}", JSON.toJSONString(execute));
            return execute.isSuccess();
        } catch (ApiRuleException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static List<MallSkuProp> buildSkuProp(Sku sku) {
        String[] specNames = sku.getSpecNames().split("@");
        String[] specValues = sku.getSpecValues().split("@");
        List<MallSkuProp> mallSkuProps = new ArrayList<>();
        for (int i = 0; i < specNames.length; i++) {
            MallSkuProp skuProp = new MallSkuProp();
            skuProp.setName(specNames[i]);
            skuProp.setValue(specValues[i]);
            skuProp.setKey(specNames[i]);
            mallSkuProps.add(skuProp);
        }
        return mallSkuProps;
    }

    @Override
    public KdzsPrintTradeCreateResponse testCreateTrade(Long id) {
        Orders orders = ordersMapper.selectByPrimaryKey(id);
        KdzsPrintTradeCreateResponse trade = createTrade(orders);
        return trade;
    }

    @Override
    public Boolean testUpdateTrade(Long id) {
        Orders orders = ordersMapper.selectByPrimaryKey(id);
        Shop shop = shopMapper.selectByPrimaryKey(orders.getTenantId());
        KdzsPrintTradeUpdateRequest updateRequest = new KdzsPrintTradeUpdateRequest();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        updateRequest.setModified(format.format(new Date()));
        updateRequest.setTid(orders.getId().toString());
        updateRequest.setStatus(KdzsOrderStatusEnum.ORDER_PAID.getStatus());
        updateRequest.setMallUserId(shop.getMallUserId());
        return updateTrade(updateRequest);
    }

    @Override
    public Boolean testUpdateTradeRefund(Long id) {
        Orders orders = ordersMapper.selectByPrimaryKey(id);
        Shop shop = shopMapper.selectByPrimaryKey(orders.getTenantId());
        List<OrderSkuVO> orderSkuVOList = orderSkuMapper.findAllByOrderId(id);
        KdzsPrintTradeRefundRequest updateRequest = new KdzsPrintTradeRefundRequest();
        updateRequest.setTid(orders.getId().toString());
        List<Long> orderSkuIds = orderSkuVOList.stream().map(OrderSkuVO::getId).collect(Collectors.toList());
        List<String> orderSkuIdStr = orderSkuIds.stream().map(x -> x + "").collect(Collectors.toList());
        updateRequest.setOidList(orderSkuIdStr);
        updateRequest.setMallUserId(shop.getMallUserId());
        updateRequest.setRefundStatus(KdzsRefundStatusEnum.REFUND_SUCCESSED.getStatus());
        BaseKdzsOpenResponse baseKdzsOpenResponse = refundTrade(updateRequest);
        return baseKdzsOpenResponse.isSuccess();
    }
}
